home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / wgdb-42.lha / wgdb-4.2 / bfd / srec.c < prev    next >
C/C++ Source or Header  |  1992-09-11  |  12KB  |  434 lines

  1. /* BFD backend for s-record objects.
  2.    Copyright (C) 1990-1991 Free Software Foundation, Inc.
  3.    Written by Steve Chamberlain of Cygnus Support <steve@cygnus.com>.
  4.  
  5. This file is part of BFD, the Binary File Descriptor library.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* S-records cannot hold anything but addresses and data, so that's all
  22.    that we implement.
  23.    
  24.    The only interesting thing is that s-records may come out of order and
  25.    there is no header, so an initial scan is required to discover the
  26.    minimum and maximum addresses used to create the vma and size of the
  27.    only section we create.  We arbitrarily call this section ".text".
  28.  
  29.    When bfd_get_section_contents is called the file is read again, and
  30.    this time the data is placed into a bfd_alloc'd area.
  31.  
  32.    Any number of sections may be created for output, we just output them
  33.    in the order provided to bfd_set_section_contents.  */
  34.  
  35. #include "bfd.h"
  36. #include "sysdep.h"
  37. #include "libbfd.h"
  38.  
  39. static char digs[] = "0123456789ABCDEF";
  40.  
  41. /* Macros for converting between hex and binary */
  42.  
  43. #define NIBBLE(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : ((x) - 'A' + 10))
  44. #define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
  45. #define TOHEX(d,x) \
  46.   ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], (x))
  47. #define    ISHEX(x)  (((x) >= '0' && (x) <= '9') || ((x) >= 'A' && (x) <= 'F'))
  48.  
  49. typedef struct {
  50.   char high;
  51.   char low;
  52. } byte_as_two_char_type;
  53.  
  54. /* The maximum number of bytes on a line is FF */
  55. #define MAXCHUNK 0xff 
  56. /* The number of bytes we fit onto a line on output */
  57. #define CHUNK 16 
  58.  
  59. /* The shape of an s-record .. */
  60. typedef struct 
  61. {
  62.   char S;
  63.   char type;
  64.   byte_as_two_char_type size;
  65.   union {
  66.     struct {
  67.       byte_as_two_char_type address[4];
  68.       byte_as_two_char_type data[MAXCHUNK];
  69.       /* If there isn't MAXCHUNK bytes of data then the checksum will 
  70.      appear earlier */
  71.       byte_as_two_char_type checksum;
  72.       char nl;
  73.     } type_3;
  74.     struct {
  75.       byte_as_two_char_type address[4];
  76.       byte_as_two_char_type data[MAXCHUNK];
  77.       byte_as_two_char_type checksum;
  78.       char nl;
  79.     } type_6;
  80.  
  81.     struct {
  82.       byte_as_two_char_type address[3];
  83.       byte_as_two_char_type data[MAXCHUNK];
  84.       byte_as_two_char_type checksum;
  85.       char nl;
  86.     } type_2;
  87.  
  88.     struct {
  89.       byte_as_two_char_type address[2];
  90.       byte_as_two_char_type data[MAXCHUNK];
  91.       byte_as_two_char_type checksum;
  92.       char nl;
  93.     } type_1;
  94.     byte_as_two_char_type data[MAXCHUNK];
  95.   } u;
  96. } srec_type;
  97.  
  98. #define enda(x) (x->vma + x->size)
  99. /* 
  100.    called once per input s-record, used to work out vma and size of data.
  101.  */
  102.  
  103. static bfd_vma low,high;
  104. static void
  105. size_srec(abfd, section, address, raw, length)
  106. bfd *abfd;
  107. asection *section;
  108. bfd_vma address;
  109. byte_as_two_char_type *raw;
  110. unsigned int length;
  111. {
  112.   if (address < low)
  113.     low = address;
  114.   if (address + length > high) 
  115.     high = address + length;
  116. }
  117.  
  118.  
  119. /*
  120.  called once per input s-record, copies data from input into bfd_alloc'd area
  121.  */
  122.  
  123. static void
  124. fillup(abfd, section, address, raw, length)
  125. bfd *abfd;
  126. asection *section;
  127. bfd_vma address;
  128. byte_as_two_char_type *raw;
  129. unsigned int length;
  130. {
  131.   unsigned int i;
  132.   bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) +  address - section->vma;
  133.   for (i = 0; i < length; i++) {
  134.     *dst = HEX(raw);
  135.     dst++;
  136.     raw++;
  137.   }
  138. }
  139.  
  140. /* Pass over an s-record file, calling one of the above functions on each
  141.    record.  */
  142.  
  143. static void
  144. pass_over(abfd, func, section)
  145.      bfd *abfd;
  146.      void (*func)();
  147.      asection *section;
  148. {
  149.   unsigned int bytes_on_line;
  150.   boolean eof = false;
  151.   bfd_vma address;
  152.   /* To the front of the file */
  153.   bfd_seek(abfd, (file_ptr)0, SEEK_SET);
  154.   while (eof == false)
  155.     {
  156.       srec_type buffer;
  157.  
  158.       /* Find first 'S' */
  159.       eof =  (boolean)(bfd_read(&buffer.S, 1, 1, abfd) != 1);
  160.       while (buffer.S != 'S' && !eof) {
  161.     eof = (boolean)(bfd_read(&buffer.S, 1, 1, abfd) != 1);
  162.       }
  163.       if (eof) break;
  164.  
  165.       bfd_read(&buffer.type, 1, 3, abfd);
  166.  
  167.       if (!ISHEX (buffer.size.high) || !ISHEX (buffer.size.low))
  168.     break;
  169.       bytes_on_line = HEX(&buffer.size);
  170.       if (bytes_on_line > MAXCHUNK/2)
  171.     break;
  172.     
  173.       bfd_read((PTR)buffer.u.data, 1 , bytes_on_line * 2, abfd);
  174.  
  175.       switch (buffer.type) {
  176.       case '6':
  177.     /* Prologue - ignore */
  178.     break;
  179.  
  180.       case '3':
  181.     address = (HEX(buffer.u.type_3.address+0) << 24)
  182.         + (HEX(buffer.u.type_3.address+1) << 16)
  183.         + (HEX(buffer.u.type_3.address+2) << 8) 
  184.         + (HEX(buffer.u.type_3.address+3));
  185.         func(abfd,section, address, buffer.u.type_3.data, bytes_on_line -1);
  186.     break;
  187.  
  188.       case '2':
  189.     address = (HEX(buffer.u.type_2.address+0) << 16)
  190.         + (HEX(buffer.u.type_2.address+1) << 8)
  191.         + (HEX(buffer.u.type_2.address+2));
  192.         func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
  193.     break;
  194.  
  195.       case '1':
  196.     address = (HEX(buffer.u.type_1.address+0) << 8) 
  197.             + (HEX(buffer.u.type_1.address+1));
  198.         func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
  199.     break;
  200.  
  201.       default:
  202.     goto end_of_file;
  203.       }
  204.     }
  205.   end_of_file: ;
  206. }
  207.  
  208.  
  209. bfd_target *
  210. srec_object_p (abfd)
  211. bfd *abfd;
  212. {
  213.   char b[4];
  214.   asection *section;
  215.   bfd_seek(abfd, (file_ptr)0, SEEK_SET);
  216.   bfd_read(b, 1, 4, abfd);
  217.   if (b[0] != 'S' || !ISHEX(b[1]) || !ISHEX(b[2]) || !ISHEX(b[3]))
  218.     return (bfd_target*) NULL;
  219.   
  220.   /* We create one section called .text for all the contents, 
  221.      and allocate enough room for the entire file.  */
  222.  
  223.   section =  bfd_make_section(abfd, ".text");
  224.   section->size = 0;
  225.   section->vma = 0xffffffff;
  226.   low = 0xffffffff;
  227.   high = 0;
  228.   pass_over(abfd, size_srec, section);
  229.   section->size = high - low;
  230.   section->vma = low;
  231.   return abfd->xvec;
  232. }
  233.  
  234.  
  235. static boolean
  236. srec_get_section_contents (abfd, section, location, offset, count)
  237. bfd *abfd;
  238. sec_ptr section;
  239. void  *location;
  240. file_ptr offset;
  241. unsigned      int count;
  242. {
  243.   if (section->used_by_bfd == (PTR)NULL) {
  244.     section->used_by_bfd = (PTR)bfd_alloc (abfd, section->size);
  245.     pass_over(abfd, fillup, section);
  246.   }
  247.   (void) memcpy((PTR)location, (PTR)((char *)(section->used_by_bfd) + offset), count);
  248.   return true;
  249. }
  250.       
  251.  
  252.  
  253. boolean
  254. srec_set_arch_mach (abfd, arch, machine)
  255. bfd *abfd;
  256. enum bfd_architecture arch;
  257. unsigned long machine;
  258. {
  259.   return bfd_default_set_arch_mach(abfd, arch, machine);
  260. }
  261.  
  262.  
  263.  
  264. boolean
  265. srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
  266. bfd *abfd;
  267. sec_ptr section;
  268. unsigned char *location;
  269. file_ptr offset;
  270. int bytes_to_do;
  271. {
  272.   bfd_vma address;
  273.   int bytes_written;
  274.  
  275.   int type;
  276.   unsigned int i;
  277.   srec_type buffer;
  278.   bytes_written = 0;
  279.   if (section->vma <= 0xffff) 
  280.     type = 1;
  281.   else if (section->vma <= 0xffffff) 
  282.     type = 2;
  283.   else
  284.     type = 3;
  285.  
  286.   buffer.S = 'S';
  287.   buffer.type = '0' + type;
  288.  
  289.   while (bytes_written < bytes_to_do) {
  290.     unsigned int size;
  291.     unsigned int check_sum;
  292.     byte_as_two_char_type *data; 
  293.  unsigned   int bytes_this_chunk = bytes_to_do - bytes_written;
  294.  
  295.     if (bytes_this_chunk > CHUNK) {
  296.       bytes_this_chunk = CHUNK;
  297.     }
  298.  
  299.     address = section->vma + offset + bytes_written;
  300.  
  301.     switch (type) {
  302.     case 3:
  303.       check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
  304.       check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
  305.       check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
  306.       check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
  307.       size = bytes_this_chunk + 5;
  308.       data = buffer.u.type_3.data;
  309.       break;
  310.     case 2:
  311.       check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
  312.       check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
  313.       check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
  314.       size = bytes_this_chunk + 4;
  315.       data = buffer.u.type_2.data;
  316.       break;
  317.  
  318.     case 1:
  319.       check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
  320.       check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
  321.       size = bytes_this_chunk + 3;
  322.       data = buffer.u.type_1.data;
  323.       break;
  324.     }
  325.  
  326.     for (i = 0; i < bytes_this_chunk; i++) {
  327.       check_sum += TOHEX(data, (location[i]));
  328.       data++;
  329.     }
  330.  
  331.     check_sum += TOHEX(&(buffer.size), size );
  332.     (void) TOHEX(data, ~check_sum);
  333.     data++;
  334.  
  335.     * ( (char *)(data)) = '\n';
  336.     bfd_write((PTR)&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
  337.  
  338.     bytes_written += bytes_this_chunk;
  339.     location += bytes_this_chunk;
  340.   }
  341.  
  342.  
  343.   return true;
  344. }
  345.  
  346. boolean
  347. srec_write_object_contents (abfd)
  348.      bfd *abfd;
  349. {
  350.   bfd_write("S9030000FC\n", 1,11,abfd);
  351.   return true;
  352. }
  353.  
  354. static int 
  355. DEFUN(srec_sizeof_headers,(abfd, exec),
  356.       bfd *abfd AND
  357.       boolean exec)
  358. {
  359. return 0;
  360. }
  361.  
  362. static asymbol *
  363. DEFUN(srec_make_empty_symbol, (abfd),
  364.       bfd*abfd)
  365. {
  366.   asymbol *new=  (asymbol *)bfd_zalloc (abfd, sizeof (asymbol));
  367.   new->the_bfd = abfd;
  368.   return new;
  369. }
  370. #define FOO PROTO
  371. #define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true
  372. #define srec_get_symtab_upper_bound (PROTO(unsigned int, (*),(bfd *)))bfd_false
  373. #define srec_get_symtab (FOO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
  374. #define srec_get_reloc_upper_bound (FOO(unsigned int, (*),(bfd*, asection *)))bfd_false
  375. #define srec_canonicalize_reloc (FOO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
  376.  
  377. #define srec_print_symbol (FOO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_type))) bfd_void
  378.  
  379. #define srec_openr_next_archived_file (FOO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
  380. #define srec_find_nearest_line (FOO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
  381. #define srec_generic_stat_arch_elt  (FOO(int, (*), (bfd *,struct stat *))) bfd_0
  382.  
  383.  
  384. #define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
  385. #define srec_core_file_failing_signal (int (*)())bfd_0
  386. #define srec_core_file_matches_executable_p (FOO(boolean, (*),(bfd*, bfd*)))bfd_false
  387. #define srec_slurp_armap bfd_true
  388. #define srec_slurp_extended_name_table bfd_true
  389. #define srec_truncate_arname (void (*)())bfd_nullvoidptr
  390. #define srec_write_armap  (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr
  391. #define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
  392. #define    srec_close_and_cleanup    bfd_generic_close_and_cleanup
  393. #define srec_bfd_debug_info_start bfd_void
  394. #define srec_bfd_debug_info_end bfd_void
  395. #define srec_bfd_debug_info_accumulate  (FOO(void, (*), (bfd *,     asection *))) bfd_void
  396.  
  397.  
  398. bfd_target srec_vec =
  399. {
  400.   "srec",            /* name */
  401.   bfd_target_srec_flavour,
  402.   true,                /* target byte order */
  403.   true,                /* target headers byte order */
  404.   (HAS_RELOC | EXEC_P |        /* object flags */
  405.    HAS_LINENO | HAS_DEBUG |
  406.    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
  407.   (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
  408.    |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
  409.   ' ',                /* ar_pad_char */
  410.   16,                /* ar_max_namelen */
  411.     1,                /* minimum alignment */
  412.   _do_getb64, _do_putb64,  _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
  413.   _do_getb64, _do_putb64,  _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
  414.  
  415.     {_bfd_dummy_target,
  416.        srec_object_p,        /* bfd_check_format */
  417.        (struct bfd_target *(*)()) bfd_nullvoidptr,
  418.        (struct bfd_target *(*)())     bfd_nullvoidptr,
  419.      },
  420.     {
  421.       bfd_false,
  422.       bfd_true,            /* mkobject */
  423.       _bfd_generic_mkarchive,
  424.       bfd_false,
  425.     },
  426.     {                /* bfd_write_contents */
  427.       bfd_false,
  428.       srec_write_object_contents,
  429.       _bfd_write_archive_contents,
  430.       bfd_false,
  431.     },
  432.   JUMP_TABLE(srec)
  433.   };
  434.